<?php
/**
 * echart 图表
 * User：liujun
 * Date：2022/3/13
 * Time：9:13 PM
 */

namespace Encore\Admin;

use Illuminate\Contracts\Support\Renderable;
use Illuminate\Support\Str;


/**
 *
 * @method EChart setXAxisAttr(array $xAxis) X轴 优先调用 xAxis方法，有其它自定义方法是调用此方法 需在xAxis方法后调用
 * @method EChart setYAxisAttr(array $yAxis) Y轴
 *
 * @method EChart setGridAttr(array $grid) 直角坐标系内绘图网格，单个 grid 内最多可以放置上下两个 X 轴，左右两个 Y 轴
 * @method EChart setBackgroundColorAttr(string $color)  背景色，默认无背景。
 * @method EChart setTitleAttr(array $title)  标题组件，包含主标题和副标题
 * @method EChart setColorAttr(array $colors) 调色盘颜色列表。如果系列没有设置颜色依次循环
 *
 * @method EChart setLegendAttrShow($bool) 设置图例是否显示, 默认为显示
 * @method EChart setLegendAttrType($type) 当图例数量过多时可设置为 scroll 默认为plain
 */
class EChart implements Renderable
{
    /**
     * echart element
     * @var string
     */
    protected string $element;

    /**
     * Echart options
     * @var array
     */
    public array $options;

    protected string $locale = 'ZH';

    protected string $theme;

    protected string $renderer = 'canvas';

    /**
     * For lazy load
     * @var bool
     */
    protected bool $lazy = false;

    /**
     * Echart canvas box size
     * @var array|string[]
     */
    protected array $size = [
        'width'  => '100%',
        'height' => '100%'
    ];


    public function __construct()
    {
        $this->element = uniqid('e-chart-');
        $this->options = [
            /**
             * default tooltip
             */
            'tooltip' => [
                'show'        => true,
                'trigger'     => 'axis',
                'axisPointer' => [
                    'type' => 'shadow',
                ],
            ],

            /**
             * default toolbox
             */
            'toolbox' => [
                'show'      => true,
                'showTitle' => false,
                'right'     => 10,
                'feature'   => [
                    'saveAsImage' => [],
                ]
            ],

            /**
             * default legend
             */
            'legend'  => [
                'show' => true,
            ],

            /**
             * default yAxis
             */
            'yAxis'   => [
                'type' => 'value',
                'data' => [],
            ],

            /**
             * default grid
             */
            'grid'    => [
                'top'    => 80,
                'left'   => 40,
                'right'  => 10,
                'bottom' => 30,
            ],
        ];
    }

    /**
     * 使用魔术方法设置图标option
     * @param string $name
     * @param array $arguments
     * @return $this
     */
    public function __call(string $name, array $arguments): static
    {
        $optionKey = Str::between($name, 'set', 'Attr');
        $attributeKey = lcfirst(Str::after($name, $optionKey . 'Attr'));
        if (strlen($attributeKey) === 0) {
            $this->options[lcfirst($optionKey)] = current($arguments);
        } else {
            $this->options[lcfirst($optionKey)][$attributeKey] = current($arguments);
        }
        return $this;
    }

    /**
     * 添加系列
     * @param array $series
     * @return EChart
     */
    public function addSeries(array $series): static
    {
        if (!isset($this->options['series'])) {
            $this->options['series'] = [];
        }
        $this->options['series'][] = $series;
        return $this;
    }

    /**
     * 自定义图表容器大小
     * @param string $width
     * @param string $height
     * @return $this
     */
    public function size(string $width, string $height): static
    {
        $this->size = [
            'width'  => $width,
            'height' => $height,
        ];
        return $this;
    }

    /**
     * 设置X轴
     * @param null $data
     * @param string $type
     * @return $this
     */
    public function xAxis($data = null, string $type = 'category'): static
    {
        if (!isset($this->option['xAxis'])) {
            $this->options['xAxis'] = [];
        }

        if (empty($data)) {
            $this->options['xAxis'][] = [
                'type' => 'category',
                'data' => [],
            ];
            return $this;
        }
        if (isset($data[0])) {
            $data = [
                'type' => 'category',
                'data' => $data,
            ];
        }
        $this->options['xAxis'][] = $data;
        return $this;
    }

    /**
     * 自定义图表主题
     * @param string $theme
     * @return $this
     */
    public function theme(string $theme): static
    {
        $this->theme = $theme;
        return $this;
    }

    /**
     * 自定义语言
     * @param string $locale
     * @return $this
     */
    public function locale(string $locale): static
    {
        $this->locale = $locale;
        return $this;
    }

    /**
     * 是否懒加载
     * @param bool $lazy
     * @return $this
     */
    public function lazy(bool $lazy = true): static
    {
        $this->lazy = $lazy;
        return $this;
    }

    public function render(): string
    {
        if (!data_get($this->options, 'legend.data')) {
            $legendData = collect($this->options['series'])->pluck('name')->toArray();
            if (empty(array_filter($legendData))) {
                $legendData = collect(data_get($this->options['series'], '0.data'))->pluck('name')->toArray();
            }
            $this->options['legend']['data'] = $legendData;
        }


        if (!data_get($this->options, 'xAxis')) {
            unset($this->options['xAxis']);
        }

        if (!data_get($this->options, 'yAxis')) {
            unset($this->options['yAxis']);
        }

        if (!data_get($this->options, 'grid')) {
            unset($this->options['grid']);
        }

        return view('admin::components.echart', [
            'element'  => $this->element,
            'option'   => $this->options,
            'renderer' => $this->renderer,
            'size'     => $this->size,
            'theme'    => $this->theme,
            'locale'   => $this->locale,
            'lazy'     => $this->lazy
        ])->render();
    }
}